package com.chuangke.login.plugin;

import cn.hutool.core.util.StrUtil;
import com.chuangke.common.exception.ChuangkeException;
import com.chuangke.login.config.LoginConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class LoginSecurityPlus {

	private static final int TIME_INTERVAL = 20;// 时间间隔（分钟）
	private static final String USER_LOGIN_FAILED_COUNT = "USER:LOGIN:FAILED:COUNT:";// redis记录用户登录失败次数key

	@Autowired
	private RedisTemplate<String, ?> redisTemplate;

	@Autowired
	private LoginConfig loginConfig;

	/**
	 * 检查是否登录超过上限
	 *
	 * @param name
	 */
	public void checkLoginRetryTimes(String name) {
		if (loginConfig.getFailedRetryTimes() < 0) {
			return;
		}
		
		String key = getKey(name);
		RedisAtomicInteger counter = getRedisCounter(key);

		if (counter.get() >= loginConfig.getFailedRetryTimes()) {
			throw new ChuangkeException("当前账号频繁登录，请稍后再试");
		}
	}

	/**
	 * 登录失败计数
	 *
	 * @param name 用户名
	 * @return
	 */
	public void loginFailed(String name) {
		if (loginConfig.getFailedRetryTimes() < 0) {
			return;
		}
		
		if (StrUtil.isBlank(name)) {
			return;
		}

		String key = getKey(name);

		RedisAtomicInteger counter = getRedisCounter(key);

		counter.getAndIncrement();// 失败次数 + 1
	}

	public void loginSuccessed(String name) {
		if (loginConfig.getFailedRetryTimes() < 0) {
			return;
		}
		
		String key = getKey(name);
		redisTemplate.delete(key);
	}

	public int getLoginFailTimes(String name) {
		if (loginConfig.getFailedRetryTimes() < 0) {
			return -1 ;
		}
		
		String key = getKey(name);
		RedisAtomicInteger counter = getRedisCounter(key);
		return counter.get();
	}

	private String getKey(String name) {
		return USER_LOGIN_FAILED_COUNT + name;
	}

	/**
	 * 根据key获取计数器
	 *
	 * @param key key
	 * @return
	 */
	private RedisAtomicInteger getRedisCounter(String key) {
		RedisAtomicInteger counter = new RedisAtomicInteger(key, Objects.requireNonNull(redisTemplate.getConnectionFactory()));
		if (counter.get() == 0) {
			// 设置过期时间，10分钟
			counter.expire(TIME_INTERVAL, TimeUnit.MINUTES);
		}
		return counter;
	}
}
